package com.zy.pool.pool;

import com.zy.pool.domain.DBbean;
import com.zy.pool.factory.ConnectionFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

/**
 * com.zy.pool.pool ConnectionPoolImpl
 *
 * @Description:
 * @date: 17:24 2018/2/6
 * @author: zhaoliang.fu
 */
public class ConnectionPoolImpl implements IConnectionPool {

    private DBbean dBbean;

    private ConnectionFactory connectionFactory;

    /**
     * 连接池活动状态
     */
    private Boolean isActive;

    /**
     * 记录创建的连接总数
     */
    private Integer contActive = 0;

    /**
     * 空闲连接
     */
    private List<Connection> freeConnection = new Vector<>();

    /**
     * 活动连接
     */
    private List<Connection> activeConnection = new Vector<>();

    /**
     * 线程连接绑定，保证事务统一
     */
    private static ThreadLocal<Connection> threadConn = new ThreadLocal<>();

    public ConnectionPoolImpl(DBbean dBbean) {
        this.dBbean = dBbean;
        if (dBbean != null) {
            connectionFactory = new ConnectionFactory.Builder().dBbean(dBbean).build();
            init();
        }
    }

    private void init() {
        for (int i = 0; i < dBbean.getInitConnections(); i++) {
            Connection connection = connectionFactory.getConnection();
            //初始化最小连接数
            if (connection != null) {
                freeConnection.add(connection);
                ++contActive;
            }
        }
        isActive = Boolean.TRUE;
    }


    /**
     * 获取连接
     * @return
     */
    @Override
    public Connection getConnection() {
        Connection conn=null;
        //判断是否超过最大连接数限制
        if(contActive<this.dBbean.getMaxActiveConnections()){
            if(freeConnection.size()>0){
                //从空闲连接集合中获取
                conn=freeConnection.get(0);
                if(conn!=null){
                    threadConn.set(conn);
                }
                freeConnection.remove(0);
            }else {
                conn=connectionFactory.getConnection();
            }
        }else {
            //重复获取连接
            //等待
            try {
                wait(dBbean.getConnTimeOut());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            conn=getConnection();
        }
        //连接可用，加入集合
        if(isValid(conn)){
            activeConnection.add(conn);
            ++contActive;
        }
        return conn;
    }

    /**
     * 判断当前连接是否可用
     * @param conn
     * @return
     */
    private boolean isValid(Connection conn) {
        try {
            if (conn == null || conn.isClosed()) {
                return Boolean.FALSE;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return Boolean.TRUE;
    }

    /**
     * 获取当前连接
     *
     * @return
     */
    @Override
    public Connection getCurrentConnection() {
        //从当前线程中取
        Connection connection = threadConn.get();
        if (!isValid(connection)) {
            connection=getConnection();
        }
        return connection;
    }

    /**
     * 释放连接
     * @param conn 
     * @throws SQLException
     */
    @Override
    public void releaseConn(Connection conn) throws SQLException {
        //连接可用并且空闲连接小于最大空闲连接
        if(isValid(conn)&&!(freeConnection.size()>dBbean.getMaxActiveConnections())){
            freeConnection.add(conn);
            activeConnection.remove(conn);
            --contActive;
            threadConn.remove();
            //获取所有等待线程
            notifyAll();
        }
    }

    //销毁
    @Override
    public void destroy() {
        List<Connection> connections=new Vector<>();
        connections.addAll(freeConnection);
        connections.addAll(activeConnection);
        for (Connection connection : connections) {
            if(isValid(connection)){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        isActive=Boolean.FALSE;
        contActive=0;
    }

    @Override
    public boolean isActive() {
        return isActive;
    }

    /**
     * 定时检查连接池
     */
    @Override
    public void checkPool() {
        if(dBbean.getIsCheckPool()){
            Long periodCheck = dBbean.getPeriodCheck();
            Long lazyCheck = dBbean.getLazyCheck();
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    // 1.对线程里面的连接状态
                    // 2.连接池最小 最大连接数
                    // 3.其他状态进行检查，因为这里还需要写几个线程管理的类，暂时就不添加了
                    System.out.println("空线池连接数："+freeConnection.size());
                    System.out.println("活动连接数：："+activeConnection.size());
                    System.out.println("总的连接数："+contActive);
                }

            },periodCheck,lazyCheck);
        }
    }
}
